package com.owc.common.lock.actuator;

import com.owc.common.converter.IExpressionActuator;
import com.owc.common.enums.ExceptionEnum;
import com.owc.common.exception.NotFoundException;
import com.owc.common.exception.ParamDeficiencyException;
import com.owc.common.lock.LockModel;
import com.owc.common.tool.ReflectionUtils;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Stream;

/**
 * @Author xiaom
 * @Date 2020/3/16 11:15
 * @Version 1.0.0
 * @Description <#{}>
 **/
@Slf4j
public class ExpressionActuator implements IExpressionActuator {
    @Override
    public String doExecute(LockModel lockModel) {

        Collection<String> expressions = lockModel.getExpression();
        if(expressions.isEmpty()){
            log.error("ExpressionActuator execute failed. Expression collection is empty.");
            throw new ParamDeficiencyException(ExceptionEnum.PARAMS_MISS_ERR);
        }

        String[] paramsNames = lockModel.getParamsNames();
        Object[] args = lockModel.getOriginalModels();

        HashMap<String,String> expressionMap = transToMap(expressions);

        List<String> keys = new ArrayList<>();

        Stream.of(paramsNames)
                .forEach(name -> {
                    if(expressionMap.containsKey(name)){
                        Object obj = getObjectByKey(args,name);
                        if(obj == null) {
                            return;
                        }
                        Object value = ReflectionUtils.getFieldValue(obj,expressionMap.get(name));
                        keys.add(value.toString());
                    }else{
                        throw new NotFoundException("Lock object attribute match failed");
                    }
                });
        return assembly(keys,lockModel.getProxyMethod().getName());
    }

    private Object getObjectByKey(Object[] args,String key){
        return Stream.of(args)
                .filter(arg -> arg.getClass().getSimpleName().toLowerCase().equals(key.toLowerCase()))
                .findFirst().orElse(null);
    }

    private HashMap<String, String> transToMap(Collection<String> expressions) {

        HashMap<String,String> map = new HashMap<>();
        for (String expression : expressions) {
            map.put(separator(expression)[0],separator(expression)[1]);
        }
        return map;
    }

    private String[] separator(String str){
        return str.split("\\.");
    }
}
